package br.edu.unoesc.minibi.service.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.persistence.EntityManager;

import br.edu.unoesc.minibi.model.InterfaceModel;
import br.edu.unoesc.minibi.service.EntityManagerUtil;
import br.edu.unoesc.minibi.service.ServiceBaseInterface;

public abstract class ServiceBaseImpl<Modelo extends InterfaceModel> implements ServiceBaseInterface<Modelo> {

	private Class<Modelo> classe;

	public void salvar(Modelo model) {
		openTransaction();
		if (model.getCodigo() != null) {
			EntityManagerUtil.getEntityManager().merge(model);
		} else {
			EntityManagerUtil.getEntityManager().persist(model);
		}
		commit();
	}

	public void remover(Modelo model) {
		openTransaction();
		EntityManagerUtil.getEntityManager().remove(model);
		commit();
	}

	public Modelo getById(Long id) {
		return EntityManagerUtil.getEntityManager().find(getTipoClasse(), id);
	}

	@Override
	public List<Modelo> getAll() {
		return EntityManagerUtil.getEntityManager().createQuery("select o from " + getTipoClasse().getName() + " o ", getTipoClasse())
				.getResultList();
	}

	private void openTransaction() {
		EntityManagerUtil.getEntityManager().getTransaction().begin();
	}

	private void commit() {
		EntityManagerUtil.getEntityManager().flush();
		EntityManagerUtil.getEntityManager().getTransaction().commit();
	}

	@SuppressWarnings("unchecked")
	private Class<Modelo> getTipoClasse() {
		if (this.classe == null) {
			Type[] types = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
			return this.classe = (Class<Modelo>) types[types.length > 1 ? 1 : 0];
		}
		return this.classe;
	}

	public EntityManager getEntityManager() {
		return EntityManagerUtil.getEntityManager();
	}
}
